home *** CD-ROM | disk | FTP | other *** search
/ Technotools / Technotools (Chestnut CD-ROM)(1993).ISO / lang_c / cug188 / header.c < prev    next >
Text File  |  1985-08-21  |  19KB  |  739 lines

  1. #include "bdscio.h"
  2.  
  3. #define OPENCMNT   1
  4. #define HEADER     2
  5. #define ATTRIBUTE  3
  6. #define ENDCMNT    4
  7. #define TITLE      5
  8. #define VERSION    6
  9. #define DATE       7
  10. #define DESC       8
  11. #define KEYWD      9
  12. #define SYSTEM    10
  13. #define FNAME     11
  14. #define WARNING   12
  15. #define CRC       13
  16. #define ALSO      14
  17. #define AUTHOR    15
  18. #define COMP      16
  19. #define REF       17
  20. #define COMMA     18
  21. #define ENDREF    19
  22. #define REFAUTH   20
  23. #define REFTTL    21
  24. #define CITATION  22
  25. #define REFCIT    23
  26. #define COLON     24
  27. #define TOOLONG   25
  28. #define SEMI      26
  29. #define QUOTE     27
  30. #define FAULT     28
  31.  
  32. #define LEXSIZE 250
  33.  
  34. #define ON   1
  35. #define OFF  0
  36.  
  37. FILE source, list;
  38.  
  39. char restart[6];
  40. char catno[20];
  41. char lexval[LEXSIZE];
  42. int stoptoken;
  43. int debug, testonly;
  44. int parsing;
  45. int number;
  46.  
  47. main(argc,argv)
  48. int argc;
  49. char **argv;
  50.  
  51. {
  52. int fnumb, diskno;
  53. int i;
  54. char *lname;
  55.  
  56. if (wildexp(&argc,&argv) == ERROR)
  57.    exit(puts("Wildexp Overflow\n"));
  58.  
  59. number = debug = testonly = OFF;
  60. fnumb = diskno = 0;
  61.  
  62. if (argc < 2) {
  63.     printf("USAGE:  header [-o<filespec>] [-t] [-d] [-nd] {<infilespec>} \n\n");
  64.     printf("   function:    Normally used to extract header information\n");
  65.     printf("                from the files in infilespec, reformatting the\n");
  66.     printf("                information in a fixed field format suitable\n");
  67.     printf("                for input to a relational database. The formatted\n");
  68.     printf("                output defaults to 'hdrout' on the current drive.\n\n");
  69.     printf("   options:     -o  use filespec for the list file name.\n");
  70.     printf("                -t  test only...checks syntax with no listing\n");
  71.     printf("                -n  number mode. Generates sequential file numbers\n");
  72.     printf("                    for all files on the disk. d is used as the\n");
  73.     printf("                    volume number. Headers consisting of only a \n");
  74.     printf("                    filename are generated for all files which don't\n");
  75.     printf("                    have a header. These are written to the list\n");
  76.     printf("                    file. Automatically sets -t, that is, since\n");
  77.     printf("                    the list file is being used to capture headers\n");
  78.     printf("                    no attempt is made to generate normal output.\n");
  79.     printf("                -d  debug...prints trace info to stdout.\n");
  80.     exit();
  81.     }
  82. lname="hdrout";
  83. for (i=1; i<argc; i++){
  84.    if (*argv[i] == '-'){
  85.       switch (*(argv[i]+1)){
  86.          case 'D': debug = ON; break;
  87.          case 'T': testonly = ON; break;
  88.          case 'N': sscanf(argv[i]+2,"%d",&diskno);
  89.                    number = ON;
  90.                    testonly = ON;
  91.                    if (diskno < 100){
  92.                       printf("\nCUG numbers start at 100!\n");
  93.                       exit();
  94.                       }
  95.                    break;
  96.          case 'O': lname= argv[i]+2;
  97.                    break;
  98.          default:  printf("\nUnrecognized option %s",argv[i]);
  99.                    break;
  100.          }
  101.       }
  102.    }
  103.  
  104. if ((!testonly) || number) openlist(lname);
  105. if (debug) printf("\n open list passed");
  106.  
  107. for (i=1; i<argc; i++){
  108.    if (*argv[i] != '-'){
  109.        printf("\n%-15s",argv[i]);
  110.        if (fopen(argv[i],source) == ERROR) printf(" ...Can't open ");
  111.        else {
  112.           if (number) {
  113.              fnumb++;
  114.              if (dofile() == OK) numfile(argv[i], diskno, fnumb);
  115.              else {
  116.                 fclose(source);
  117.                 fprintf(list,"/* HEADER: CUG%03d.%02d; FILENAME: %s; */\n",
  118.                              diskno,fnumb,argv[i]);
  119.                 }
  120.              }
  121.           else {
  122.              dofile();
  123.              fclose(source);
  124.              }
  125.           }
  126.        }
  127.     }
  128. if ((!testonly) || number){
  129.    fprintf(list,"%c",0x1a);
  130.    fflush(list);
  131.    fclose(list);
  132.    }
  133. }
  134.  
  135. /*
  136.    process a single file, adding results to output file
  137. */
  138. int dofile()
  139. {
  140. int att;
  141. int laterpass;
  142.  
  143. parsing = FAULT;
  144. laterpass = setjmp(restart);
  145. if (laterpass) return OK;
  146.  
  147. if (scantoken() != OPENCMNT) {
  148.    printf(" ...File doesn't begin with comment");
  149.    return !OK;
  150.    }
  151. if (scantoken() != HEADER) {
  152.    printf(" ...First comment isn't header ");
  153.    return !OK;
  154.    }
  155. printf(" ...Processing header");
  156. if (scantoken() != COLON) {
  157.    printf(" ...No colon after header keywork");
  158.    return !OK;
  159.    }
  160. scancatno(); /* sets catno as sideeffect */
  161. if (scantoken() != SEMI) faterr(4,"Expecting semi after cat. no.");
  162. while (tokentype(att=scantoken())==ATTRIBUTE) scanatt(att);
  163. if (stoptoken != ENDCMNT) faterr(5,"Header must end with comment delimiter");
  164. while(dohdr()==OK);  /*do following headers */
  165. return OK;
  166. }
  167.  
  168. int dohdr()
  169. {
  170. int att;
  171. int laterpass;
  172.  
  173. parsing = FAULT;
  174. laterpass = setjmp(restart);
  175. if (laterpass) return !OK;
  176.  
  177. if (scantoken() != OPENCMNT) {
  178.    return !OK;
  179.    }
  180. if (scantoken() != HEADER) {
  181.    return !OK;
  182.    }
  183. printf("\n                ...and another");
  184. if (scantoken() != COLON) {
  185.    printf(" ...No colon after header keywork");
  186.    return !OK;
  187.    }
  188. scancatno(); /* sets catno as sideeffect */
  189. if (scantoken() != SEMI) faterr(4,"Expecting semi after cat. no.");
  190. while (tokentype(att=scantoken())==ATTRIBUTE) scanatt(att);
  191. if (stoptoken != ENDCMNT) faterr(5,"Header must end with comment delimiter");
  192. /* always scans one token beyond end of attribute, leaves */
  193. return OK;
  194. }
  195.  
  196. int scanatt(att)
  197. int att;
  198.  
  199. {
  200. parsing = att;
  201. if (scantoken() != COLON)
  202.     faterr(10, "Attribute name must be followed by colon");
  203.  
  204. switch(att){
  205.    case TITLE:
  206.           if (scanitem() != OK) faterr(10,"ITEM must follow TITLE");
  207.           generate(catno,TITLE,lexval);
  208.           scantoken();
  209.                break;
  210.    case VERSION:
  211.           if (scannumber() != OK) faterr(11,"version number needed");
  212.           generate(catno,VERSION,lexval);
  213.           scantoken();
  214.           break;
  215.    case DATE:
  216.           if (scandate() != OK) faterr(12,"date needed");
  217.           generate(catno,DATE,lexval);
  218.           scantoken();
  219.           break;
  220.    case DESC:
  221.           if (scanstring(DESC)==TOOLONG)
  222.               faterr(13,"string too long in description");
  223.                /*scanstring breaks its output into lines and outputs it
  224.                  as a side effect. More than 30 lines is treated as an
  225.                  error (TOOLONG) */
  226.           scantoken();
  227.           break;
  228.    case KEYWD:
  229.           if (scanlist(KEYWD)!= OK) faterr(14,"Bad keyword list ");
  230.           break;
  231.    case SYSTEM:
  232.           if (scanlist(SYSTEM)!= OK) faterr(15,"Bad System list");
  233.           break;
  234.    case FNAME:
  235.           if (scanfname() != OK) faterr(16,"Poorly formed filename");
  236.           generate(catno,FNAME,lexval);
  237.           scantoken();
  238.           break;
  239.    case WARNING:
  240.           if (scanstring(WARNING)==TOOLONG)
  241.               faterr(17,"string too long in warning field");
  242.           scantoken();
  243.           break;
  244.    case CRC:
  245.           if (scanhex() != OK) faterr(18,"poorly formed CRC number");
  246.           generate(catno,CRC,lexval);
  247.           scantoken();
  248.           break;
  249.    case ALSO:
  250.           if (scanlist(ALSO)!= OK) faterr(19,"Bad See-Also list"); break;
  251.    case AUTHOR:
  252.           if (scanlist(AUTHOR)!= OK) faterr(20,"Bad Author list");
  253.           break;
  254.    case COMP:
  255.           if(scanlist(COMP)!=OK) faterr(21,"Bad Compiler List"); break;
  256.    case REF:
  257.           scanreflist(); /*generates output as side-effect*/
  258.           break;
  259.    default: faterr(22,"Unrecognized attribute");
  260.    }
  261. if (stoptoken != SEMI) faterr(23,"semi-colons must terminate attributes");
  262. }
  263.  
  264. int scanlist(type)
  265. int type;
  266.  
  267. {
  268. do {
  269.     if (scanitem()!= OK) {
  270.         errmsg(30,"Item poorly formed");
  271.         return(!OK);
  272.         }
  273.     generate(catno,type,lexval);
  274.     } while (scantoken()==COMMA);
  275. return(OK);
  276. }
  277.  
  278. scanreflist()
  279.  
  280. {
  281. do{
  282.    if (scanref() != OK)
  283.       faterr(40,"Reference poorly formed");
  284.    /* generates output as side effect */
  285.    } while (scantoken()== SEMI);
  286. if (stoptoken!=ENDREF)
  287.     faterr(41,"List of references must end with ENDREF keyword");
  288. scantoken(); /*to load semicolon into stoptoken */
  289. }
  290.  
  291. int scanref()
  292.  
  293. {
  294. if (scantoken()!=AUTHOR) {
  295.     errmsg(50,"reference must begin with AUTHORS:");
  296.     return !OK;
  297.     }
  298. if (scantoken()!=COLON) {
  299.     errmsg(54,"AUTHOR keyword must be followed by colon");
  300.     return !OK;
  301.     }
  302. if (scanlist(REFAUTH)!=OK) {
  303.     errmsg(51,"Bad reference list");
  304.     return !OK;
  305.     }
  306. if (stoptoken!= SEMI){
  307.     errmsg(52,"Authors in reference must end with semicolon");
  308.     return !OK;
  309.     }
  310. if (scantoken() != TITLE) {
  311.     errmsg(52,"Title must follow authors in reference");
  312.     return !OK;
  313.     }
  314. if (scantoken() != COLON) {
  315.     errmsg(53,"TITLE keyword must be followed by colon");
  316.     return !OK;
  317.     }
  318. if (scanstring(REFTTL)==TOOLONG){
  319.     errmsg(55,"title in reference too long--missing end quote?");
  320.     return !OK;
  321.     }
  322. if (scantoken()!= SEMI){
  323.     errmsg(56,"title must end with semicolon in reference");
  324.     return !OK;
  325.     }
  326. if (scantoken()!=CITATION){
  327.     errmsg(57,"CITATION must follow title in reference");
  328.     return !OK;
  329.     }
  330. if (scantoken() != COLON){
  331.     errmsg(58,"Colon must follow keyword CITATION in reference");
  332.     return !OK;
  333.     }
  334. if (scanstring(REFCIT)==TOOLONG){
  335.     errmsg(59,"Citation too long -- missing end quote?");
  336.     return !OK;
  337.     }
  338. return OK;
  339. }
  340.  
  341. generate(fileid,fldtype,str)
  342. char *fileid, *str;
  343. int fldtype;
  344.  
  345. {
  346. if (!testonly)
  347.    fprintf(list,"%3d %9s %s\n",fldtype,fileid,ljust(str));
  348. }
  349.  
  350. int scanstring(boss)
  351. int boss;
  352.  
  353. {
  354. int i, lines;
  355. int tmp;
  356. char buff[120];
  357. char *tbuf;
  358.  
  359. lines = 0;
  360. tmp = 0;
  361.  
  362. if (scantoken() != QUOTE) errmsg(51,"missing opening quote");
  363. do {
  364.    i = 0;
  365.    lines += 1;
  366.    tbuf=buff;
  367.    while ((i++ < 80) && ((tmp = getc(source))!=0x0a)
  368.          && (tmp != '"'))
  369.          if (tmp != 0x0d)  *tbuf++ = tmp;
  370.    *tbuf = 0;
  371.    if (i >= 80) {
  372.       errmsg(52,"string line over 80 chars -- missing end quote??");
  373.       }
  374.    generate(catno,boss,buff);
  375.    } while ((tmp != '"') && (lines < 15));
  376. return (lines > 15)? TOOLONG: OK;
  377. }
  378.  
  379. int scandate()
  380. {
  381. int i,n,mo,day,year;
  382. char buff[256];
  383. char *tbuf;
  384.  
  385. n=mo=day=year=i=0;
  386. tbuf=buff;
  387. while (((*tbuf++ = getc(source)) != ';') && (i++ < 250));
  388. if (i > 250) {
  389.    errmsg(55,"unable to find date terminator");
  390.    return !OK;
  391.    }
  392. ungetc(';',source);
  393. *tbuf = 0;
  394. if (debug) printf("scanning /%s/ in date\n",buff);
  395. if ((n=sscanf(buff,"%d/%d/%d",&mo,&day,&year))!=3){
  396.    if (debug) printf("fscanf returns %d with %d %d %d\n",n,mo,day,year);
  397.    return !OK;
  398.    }
  399. if (debug) printf("fscanf returns %d with %d %d %d\n",n,mo,day,year);
  400. if ((mo < 1) || (mo > 12) || (day < 1) || (day > 31)){
  401.    return !OK;
  402.    }
  403. if ((year < 100) && (year >50)) year = 1900 + year;
  404. sprintf(lexval,"%02d/%02d/%04d",mo,day,year);
  405. return OK;
  406. }
  407.  
  408. int scantoken()
  409.  
  410. {
  411. int rval;
  412.  
  413. fillex();
  414. if (debug) printf("at scantoken start, lexval=/%s/\n",lexval);
  415. switch (*lexval){
  416.    case '/': if (getc(source) == '*') rval =  OPENCMNT;
  417.              else rval = FAULT;
  418.              break;
  419.    case '*': if (getc(source) == '/') rval =  ENDCMNT;
  420.              else rval = FAULT;
  421.              break;
  422.    case ',': rval =  COMMA; break;
  423.    case '"': rval =  QUOTE; break;
  424.    case ':': rval =  COLON; break;
  425.    case ';': rval =  SEMI; break;
  426.    default:
  427.       if (!strcmp(lexval,"HEADER")) rval =  HEADER;
  428.       else if (!strcmp(lexval,"TITLE")) rval =  TITLE;
  429.       else if (!strcmp(lexval,"VERSION")) rval =  VERSION;
  430.       else if (!strcmp(lexval,"DATE")) rval =  DATE;
  431.       else if (!strcmp(lexval,"DESCRIPTION")) rval =  DESC;
  432.       else if (!strcmp(lexval,"KEYWORDS")) rval =  KEYWD;
  433.       else if (!strcmp(lexval,"SYSTEM")) rval =  SYSTEM;
  434.       else if (!strcmp(lexval,"FILENAME")) rval =  FNAME;
  435.       else if (!strcmp(lexval,"WARNINGS")) rval =  WARNING;
  436.       else if (!strcmp(lexval,"CRC")) rval =  CRC;
  437.       else if (!strcmp(lexval,"SEE-ALSO")) rval =  ALSO;
  438.       else if (!strcmp(lexval,"AUTHORS")) rval =  AUTHOR;
  439.       else if (!strcmp(lexval,"COMPILERS")) rval =  COMP;
  440.       else if (!strcmp(lexval,"REFERENCES")) rval =  REF;
  441.       else if (!strcmp(lexval,"ENDREF")) rval =  ENDREF;
  442.       else if (!strcmp(lexval,"CITATION")) rval =  CITATION;
  443.       else rval =  ERROR;
  444.       }
  445. stoptoken = rval;
  446. if (debug) printf("\nscantoken returns %d /%s/",rval,lexval);
  447. return rval;
  448. }
  449.  
  450. scancatno()
  451.  
  452. {
  453. int n,volume,file;
  454. char *tmp;
  455. char locbuf[512];
  456. char waste[512];
  457. char dot;
  458.  
  459. tmp=locbuf;
  460. n=510;
  461. do {
  462.     *tmp=getc(source);
  463.     if (!n--) faterr(73,"no semicolon following cat no.");
  464.     }while ( *tmp++ != ';');
  465. ungetc(';',source);
  466. *(--tmp) = 0;
  467. if ((n=sscanf(locbuf,"%sCUG%d%c%d",waste,&volume,&dot,&file))!=4){
  468.     if (debug) printf("\nfscanf returns %d",n);
  469.     if (debug) printf("\nfscanf returns /%s/ %d %d %d",waste,volume,dot,file);
  470.     faterr(71,"Bad catalog number");
  471.     }
  472. if (volume < 100) errmsg(72,"CUG disks begin at 100!");
  473. if (file > 99) errmsg(74,"File number greater than 100.");
  474. if (dot != '.') errmsg(75,"Period separates disk and file no.");
  475. sprintf(catno,"CUG%03d.%02d",volume,file);
  476. }
  477.  
  478. int tokentype(tkn)
  479. int tkn;
  480.  
  481. {
  482. switch (tkn){
  483.    case TITLE:
  484.    case VERSION:
  485.    case DATE:
  486.    case DESC:
  487.    case KEYWD:
  488.    case SYSTEM:
  489.    case FNAME:
  490.    case WARNING:
  491.    case CRC:
  492.    case ALSO:
  493.    case AUTHOR:
  494.    case COMP:
  495.    case REF:
  496.         return ATTRIBUTE;
  497.    default:
  498.         return !ATTRIBUTE;
  499.    }
  500. }
  501.  
  502. int scanitem()
  503. {
  504. int tmp;
  505. char *tpt;
  506.  
  507. tpt=lexval;
  508. do {
  509.    stoptoken = *tpt++ = getc(source);
  510.    } while ((stoptoken != ',') && (stoptoken != ';'));
  511. *(--tpt) = 0;
  512. ungetc(stoptoken,source);
  513. tmp=strlen(lexval);
  514. if ((tmp>40)||(tmp<1)) return !OK;
  515. return OK;
  516. }
  517.  
  518. fillex()
  519. {
  520. int i;
  521. char *pnt;
  522.  
  523. if (debug) printf("\nfillex entered");
  524. pnt=lexval;
  525. i=0;
  526. do{
  527.    *pnt=getc(source);
  528.    if (debug) printf("\n  getc=%02.2x",*pnt);
  529.    } while (isspace(*pnt));
  530. if (debug) printf("\nwhitespace loop passed");
  531. stoptoken = *pnt;
  532. if (!isterm(*pnt)){
  533.     do{
  534.         *(++pnt) = getc(source);
  535.        }while (!isterm(*pnt) && (i++ < (LEXSIZE-3)));
  536.     stoptoken = *pnt--;
  537.     ungetc(stoptoken,source);
  538.     }
  539. *(++pnt)='\0';
  540. if (debug) printf("\nfillex exited lexval = /%s/",lexval);
  541. }
  542.  
  543. faterr(id,str)
  544. int id;
  545. char *str;
  546.  
  547. {
  548. char *parstask;
  549. switch (parsing){
  550.    case OPENCMNT:
  551.    case HEADER:
  552.    case ATTRIBUTE: parstask = "header beginning"; break;
  553.    case TITLE:     parstask = "title";break;
  554.    case VERSION:   parstask = "version"; break;
  555.    case DATE:      parstask = "date"; break;
  556.    case DESC:      parstask = "description"; break;
  557.    case KEYWD:     parstask = "keywords"; break;
  558.    case SYSTEM:    parstask = "operating systems"; break;
  559.    case FNAME:     parstask = "filename"; break;
  560.    case WARNING:   parstask = "warnings"; break;
  561.    case CRC:       parstask = "crck"; break;
  562.    case ALSO:      parstask = "see-also"; break;
  563.    case AUTHOR:    parstask = "authors"; break;
  564.    case COMP:      parstask = "compilers"; break;
  565.    case REF:       parstask = "references"; break;
  566.    default:        parstask = 0; break;
  567.    }
  568.  
  569. if (parstask) printf("\n               %3d: %s in %s field",id,str,parstask);
  570. else          printf("\n               %3d: %s",id,str);
  571. longjmp(restart,1);
  572. }
  573.  
  574. int readwd(pnt)
  575. char *pnt;
  576.  
  577. {
  578. int i;
  579.  
  580. i=0;
  581. while (isspace(*pnt = getc(source))) pnt++;
  582. while ((*pnt != '"') && (!isspace(*pnt))){
  583.     pnt++;i++;
  584.     *pnt = getc(source);
  585.     }
  586. ungetc(*pnt, source);
  587. *pnt ='\0';
  588. return i;
  589. }
  590.  
  591. int scanhex()
  592. {
  593. int val;
  594.  
  595. if (fscanf(source,"%x",&val)!= 1) return !OK;
  596. sprintf(lexval,"%04x",val);
  597. return OK;
  598. }
  599.  
  600. int scannumb()
  601.  
  602. {
  603. int fract;
  604.  
  605. fillex();
  606.  
  607. if (!isdigit(lexval[0])) {
  608.    errmsg(95,"version number must begin with digit");
  609.    return !OK;
  610.    }
  611. if (lexval[1] == '.'){
  612.    if (!isdigit(lexval[2])){
  613.       errmsg(90,"digit must follow '.' in version number");
  614.       return !OK;
  615.       }
  616.    if (isdigit(lexval[3]) && isdigit(lexval[4])){
  617.       errmsg(91,"only two digits may follow '.' in version number");
  618.       return !OK;
  619.       }
  620.    return OK;
  621.    }
  622. else if (lexval[2] == '.'){
  623.    if (!isdigit(lexval[3])){
  624.       errmsg(92,"digit must follow '.' in version number");
  625.       return !OK;
  626.       }
  627.    if (isdigit(lexval[4]) && isdigit(lexval[5])){
  628.       errmsg(93,"only two digits may follow '.' in version number");
  629.       return !OK;
  630.       }
  631.    return OK;
  632.    }
  633. else {
  634.    errmsg(94,"version number must contain period");
  635.    return !OK;
  636.    }
  637. }
  638.  
  639. int scanfname()
  640. {
  641. fillex();
  642. return OK;
  643. }
  644.  
  645. opensource(str)
  646. char *str;
  647.  
  648. {
  649. fopen(str,source);
  650. }
  651.  
  652. openlist(str)
  653. char *str;
  654. {
  655. fcreat(str,list);
  656. }
  657.  
  658. int isspace(ch)
  659. char ch;
  660.  
  661. {
  662. return (ch <= ' ');
  663. }
  664.  
  665. int isterm(ch)
  666. char ch;
  667.  
  668. {
  669. switch (ch) {
  670.    case 0x0d:
  671.    case 0x0a:
  672.    case ' ':
  673.    case ':':
  674.    case ',':
  675.    case '"':
  676.    case ';':
  677.    case '*':
  678.    case '/':
  679.              return TRUE;
  680.              break;
  681.    default: return FALSE;
  682.    }
  683. }
  684.  
  685. char *ljust(str)
  686. char *str;
  687.  
  688. {
  689. while ((*str) && (isspace(*str))) str++;
  690. return str;
  691. }
  692.  
  693. numfile(name,disk,file)
  694. char *name;
  695. int disk, file;
  696.  
  697. {
  698. char linebuf[512];
  699. FILE newfile;
  700. int ch,i;
  701. int st;
  702.  
  703. i=0;
  704. st=fclose(source);
  705. if (debug) printf("\nnum: close source returns %d",st);
  706. st=fopen(name,source);
  707. if (debug) printf("\nnum: fopen source returns %d",st);
  708. st=fcreat("HDR.$$$",newfile);
  709. if (debug) printf("\nnum: fcreat newfile returns %d",st);
  710. while((ch = getc(source)) != ':') putc(ch,newfile);
  711. putc(ch,newfile);
  712. fprintf(newfile,"  CUG%03d.%02d;",disk,file);
  713. while ((getc(source) != ';') && (i++ < 200));
  714. if (i >= 200) {
  715.    printf(" ...volume number must end in semicolon");
  716.    st= fclose(newfile);
  717.    if(debug) printf("\nnum: fclose(newfile) returns %d",st);
  718.    st= unlink("HDR.$$$");
  719.    if (debug) printf("\nnum: unlink(temp) returns %d",st);
  720.    st=fclose(source);
  721.    if (debug) printf("\nnum: fclose source returns %d",st);
  722.    return;
  723.    }
  724. while(fgets(linebuf,source)) fputs(linebuf,newfile);
  725. fprintf(newfile,"\n%c",0x1a);
  726. st=fflush(newfile);
  727. if (debug) printf("\nnum: fflush newfile returns %d",st);
  728. st=fclose(newfile);
  729. if (debug) printf("\nnum: fclose newfile returns %d",st);
  730. st=fclose(source);
  731. if (debug) printf("\nnum: last fclose source returns %d",st);
  732. st=rename(name,"NUM.BAK");
  733. if (debug) printf("\nnum: rename source returns %d",st);
  734. st=rename("HDR.$$$",name);
  735. if (debug) printf("\nnum: rename temp returns %d",st);
  736. st=unlink("NUM.BAK");
  737. if (debug) printf("\nnum: unlink bak returns %d",st);
  738. }
  739.